/*
 *  CEScrollView.h
 *  LID Library
 *
 *  Created by Alexander Trutchenko on 09/11/11.
 *  Copyright 2011 League of Independent Developers. All rights reserved.
 *
 */

#ifndef __CE_ScrollView_h__
#define __CE_ScrollView_h__


#include "cocos2dx_extentions/nodes/CENodeScissored.h"

namespace cocos2d
{
class CCLayerColor;
}

namespace cocosext {

#define CE_SCROLLVIEW_MAX_SPEED 700.f
#define CE_SCROLLVIEW_ACCEL_MUL_FOR_MAX_SPEED 0.5f
#define CE_SCROLLVIEW_ACCEL_MUL_FOR_MIN_SPEED 1.f
#define CE_SCROLLVIEW_MIN_SPEED 45.f

#define CE_SCROLLVIEW_MOVE_FILTER_SIZE 10
#define CE_SCROLLVIEW_MOVE_CLEAR_FILTER_TIME 0.3f
#define CE_SCROLLVIEW_END_CLEAR_FILTER_TIME 0.15f

#define CE_SCROLLVIEW_SCROLLBAR_DELAY 0.2f
#define CE_SCROLLVIEW_SCROLLBAR_FADE_IN_TIME 0.2f
#define CE_SCROLLVIEW_SCROLL_BAR_DEFAULT_WIDTH 7

typedef enum
{
	eCE_SAA_X_left = 0,
	eCE_SAA_X_center,
	eCE_SAA_X_right,
} ECEScrollableAreaAllignOnSizeChangeX;

typedef enum
{
	eCE_SAA_Y_bottom = 0,
	eCE_SAA_Y_center,
	eCE_SAA_Y_top,
} ECEScrollableAreaAllignOnSizeChangeY;

/////////////////////////////////////////////////////
//
/** CEScrollView 
* 
*/
/////////////////////////////////////////////////////

class CEScrollBar;

class CEScrollView : public cocos2d::CCLayer
{
protected:
//Frame and scrollable area
	cocos2d::CCNode* _scrollableArea;
	CENodeScissored<cocos2d::CCNode>* _frame;
	ECEScrollableAreaAllignOnSizeChangeX _saaX;
	ECEScrollableAreaAllignOnSizeChangeY _saaY;

//Background (under frame)
	cocos2d::CCNode* _background; //Have the same sizeas frame. Resize with frame (setContentSize)

//Horizontal scrolling
	bool _horizontalScrolling;
	CEScrollBar* _horizontalScrollBar;

//Vertical scrolling
	bool _verticalScrolling;
	CEScrollBar* _verticalScrollBar;

//Scrollbar options
	bool _insideScrollbar;
	bool _hiddenScrollbar;
	bool _areScrollBarsShown;


//Touch processing
	int _touchPriority;
	cocos2d::CCTouch* _currentTouch;
	cocos2d::CCPoint _touchBeginPoint;
	cocos2d::CCPoint _latestTouchMovePoint;
	bool _isMovedOnLatestTouchMove;
	cocos2d::ccTime _latestTime;
	cocos2d::ccTime _touchBeginTime;
	cocos2d::ccTime _touchEndTime;

//Time and moving
	cocos2d::CCPoint _startPoint;
	cocos2d::ccTime _accumulatedTime;

	cocos2d::CCPoint _touchBeginAreaPos;
	cocos2d::CCPoint _touchMoveAreaPos;

	cocos2d::CCPoint _speedVector;
	cocos2d::CCPoint _accelVector;
	cocos2d::CCPoint _speedAccumulator[CE_SCROLLVIEW_MOVE_FILTER_SIZE];
	unsigned int _accumulatorCursor;
	bool _isSelfMoving;


// Enable-disable property
	unsigned int _disableCount;
	
private:
	CEScrollView();

protected:
	CEScrollView(bool horizontalScrolling,
				 bool verticalScrolling,
				 bool insideScrollbar,
				 bool hiddenScrollbar);

public:
    virtual ~CEScrollView() {;}

	    /* Static constructor */
    static CEScrollView* node(cocos2d::CCNode* scrollableArea,
							  cocos2d::CCNode* background = NULL,
							  bool horizontalScrolling = true,
							  CEScrollBar* horizontalScrollBar = NULL,
							  bool verticalScrolling = true,
							  CEScrollBar* verticalScrollBar = NULL,
							  bool insideScrollbar = true,
							  bool hiddenScrollbar = true);

protected:
    virtual bool init(cocos2d::CCNode* scrollableArea,
					  cocos2d::CCNode* background,
					  CEScrollBar* horizontalScrollBar,
					  CEScrollBar* verticalScrollBar);

public:
//Main interface
	void setIsEnabled(bool isEnabled);
	bool getIsEnabled() const { return (_disableCount == 0); }
	void setRelativeScrollableAreaPosition(cocos2d::CCPoint pos); // CCPoint(0.f..1.f, 0.f..1.f)
	
public:
//Cocos2d interface
	virtual void setRotation(float fRotation);
	virtual void setContentSize(const cocos2d::CCSize& contentSize);
	virtual void registerWithTouchDispatcher();
	

// Touch processing
	virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    virtual void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    virtual void ccTouchCancelled(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);

	inline bool isMovedOnLatestTouchMove() const { return _isMovedOnLatestTouchMove; }
	inline float moveDeltaVertically() const { return _touchMoveAreaPos.y - _touchBeginAreaPos.y; }
	inline float moveDeltaHorizontally() const { return _touchMoveAreaPos.x - _touchBeginAreaPos.x; }
	inline bool isSelfMoving() const { return _isSelfMoving; }
	virtual void setTouchPriority(int newPriority); 

//Scrollable area properties
	ECEScrollableAreaAllignOnSizeChangeX getScrollableAreaAllignOnSizeChangeX() const { return _saaX; }
	void setScrollableAreaAllignOnSizeChangeX(ECEScrollableAreaAllignOnSizeChangeX saaX) { _saaX = saaX; }
	ECEScrollableAreaAllignOnSizeChangeY getScrollableAreaAllignOnSizeChangeY() const { return _saaY; }
	void setScrollableAreaAllignOnSizeChangeY(ECEScrollableAreaAllignOnSizeChangeY saaY) { _saaY = saaY; }

protected:
	virtual void updateTime(cocos2d::ccTime dt);
	virtual void doSetIsEnabled(bool isEnabled);
	
	virtual void onChangeScrollableArea();
	virtual void onMoveScrollableArea();

	cocos2d::CCSize calculateFrameSizeForNewContentSize(cocos2d::CCSize newContentSize);

private:
	cocos2d::CCPoint calculateNewPosition(cocos2d::CCTouch *pTouch);
	void validateScrollableAreaPosition();

}; //CEScrollView


}; // end namespace cocosext

#endif // __CE_ScrollView_h__
